package com.ms.pda.base

import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.KeyboardUtils
import com.blankj.utilcode.util.ToastUtils
import com.gyf.immersionbar.ImmersionBar
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.ms.architecture.base.BaseApplication
import com.ms.architecture.base.DataBindingActivity
import com.ms.architecture.status.NetworkStateManager
import com.ms.pda.R
import com.ms.pda.messenger.AppMessenger
import com.ms.pda.model.KeyMap
import com.ms.pda.net.ResponseError
import com.ms.pda.utils.DialogUtil

abstract class BaseActivity : DataBindingActivity() {

    private var mActivityProvider: ViewModelProvider? = null
    private var mApplicationProvider: ViewModelProvider? = null

    private var mLoading: BasePopupView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(getNetworkStateManager())
        ImmersionBar.with(this)
            .statusBarColor(statusBarColor())
            .statusBarDarkFont(statusBarDarkFont())
            .fitsSystemWindows(true)
            .init()
        initViews()
        loadData()
    }

    protected open fun statusBarColor(): Int {
        return R.color.white
    }

    protected open fun statusBarDarkFont(): Boolean {
        return true
    }

    protected open fun initViews() {}

    protected open fun loadData() {}

    protected open fun <T : ViewModel> getActivityScopeViewModel(modelClass: Class<T>): T {
        if (mActivityProvider == null) {
            mActivityProvider = ViewModelProvider(this)
        }
        return mActivityProvider!![modelClass]
    }

    protected open fun <T : ViewModel> getApplicationScopeViewModel(modelClass: Class<T>): T {
        if (mApplicationProvider == null) {
            mApplicationProvider = ViewModelProvider((this.applicationContext as BaseApplication))
        }
        return mApplicationProvider!![modelClass]
    }

    protected open fun handleResponseError(throwable: Throwable) {
        dismiss()
        DialogUtil.getErrorDialog(this, ResponseError(throwable), null)
            .show()
    }

    private fun getNetworkStateManager(): NetworkStateManager {
        val appMsger = getApplicationScopeViewModel(AppMessenger::class.java)
        return NetworkStateManager(object : NetworkStateManager.NetworkStateCallback {
            override fun networkAvailable() {
            }

            override fun networkUnAvailable() {
                if (appMsger.networkMode.value == KeyMap.ONLINE) {
                    ToastUtils.showLong(getString(R.string.network_unavailable))
                }
            }

            override fun networkConnected() {
                if (appMsger.networkMode.value != KeyMap.ONLINE) {
                    DialogUtil.getTipPopupView(
                        this@BaseActivity,
                        getString(R.string.network_connected),
                        null
                    )
//                    appMsger.networkMode.value = KeyMap.ONLINE
                }
            }

            override fun networkDisconnected() {
                if (appMsger.networkMode.value != KeyMap.OFFLINE) {
                    DialogUtil.getTipPopupView(
                        this@BaseActivity,
                        getString(R.string.network_disconnected),
                        null
                    )
//                    appMsger.networkMode.value = KeyMap.OFFLINE
                }
            }
        })
    }

    fun getLoading(): BaseActivity {
        if (mLoading == null) mLoading = XPopup.Builder(this)
            .isDestroyOnDismiss(false)
            .dismissOnTouchOutside(false)
            .dismissOnBackPressed(false)
            .hasShadowBg(false)
            .asLoading()
        return this
    }

    fun show() {
        if (mLoading == null) return
        if (mLoading!!.isShow) return
        mLoading?.show()
    }

    private fun dismiss() {
        mLoading?.smartDismiss()
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        if (ev?.action == MotionEvent.ACTION_DOWN) {
            val v: View? = currentFocus
            v?.let {
                if (isShouldHideKeyboard(it, ev)) {
                    it.clearFocus()
                    KeyboardUtils.hideSoftInput(this)
                }
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    // Return whether touch the view.
    private fun isShouldHideKeyboard(v: View, event: MotionEvent): Boolean {
        if (v is EditText) {
            val l = intArrayOf(0, 0)
            v.getLocationOnScreen(l)
            val left = l[0]
            val top = l[1]
            val bottom = top + v.getHeight()
            val right = left + v.getWidth()
            return !(event.rawX > left && event.rawX < right && event.rawY > top && event.rawY < bottom)
        }
        return false
    }

    override fun onBackPressed() {
        ActivityUtils.finishActivity(this)
    }
}